/**
 * \file loadedlib.hpp
 * \brief Dynamic Loader of Libraries
 * \author Michael.M.M.
 * \date january 11th 2011
 */
#ifndef LOADEDLIB_HPP
# define LOADEDLIB_HPP

# include <iostream>
# include <string>

# ifdef WIN32
#  include <direct.h>
#  include <windows.h>
#  define LIBTYPE HINSTANCE
#  define LIB_EXTENSION ".dll"
# else
#  include <sys/types.h>
#  include <dlfcn.h>
#  define LIBTYPE void*
#  define LIB_EXTENSION ".so"
# endif

namespace Utils
{
  /*! \class LoadedLib
  * \brief Interface for dynamicly loaded libraries.
  */
  class		LoadedLib
  {
  public:
    class Factory
    {
    public:
      static LoadedLib* New(const std::string& libName);
    };
    
    ~LoadedLib(void);
    
    /*! \brief Get the last error
     * \return A string describing the last error, or 0 if last operation was successfull (Warning: not working using WIN32 API right now).
     */
    const char*         GetLastError(void) const;
    
    /*! \brief GetFunction
    * \param symbol : Name of the function you're trying to get.
    * \return Returns 0 in case of failure, or a pointer to the function you tried to load.
    */
    
#ifndef WIN32
    template<typename T>
    T		GetFunction(const std::string& symbol) const
    {
      T		function;

      function = (T)(dlsym(lib, symbol.c_str()));
      error = dlerror();
      if (error)
	function = 0;
      return (function);
    }
#else
    template<typename T>
    T		GetFunction(const std::string& symbol) const
    {
      T		function;

      function = (T)(GetProcAddress(lib, symbol.c_str()));
      return (function);
    }
#endif

  private:
    LoadedLib(LIBTYPE);
    
    const char*         error;
    bool		loaded;
    LIBTYPE		lib;
  };
}

#endif
